import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Properties;

import com.google.gdata.client.calendar.CalendarService;
import com.google.gdata.data.PlainTextConstruct;
import com.google.gdata.data.calendar.CalendarEventEntry;

import twitter4j.Status;
import twitter4j.Twitter;


public class TwitterMonitor {
	static final String PROP_FILE_NAME = "TwitterMonitor.properties";
	static final String ENABLED = "enabled";
	// Property Constants
	static final String TWITTER_USER_NAME = "twitterUserName";
	static final String TWITTER_PASS = "twitterPass";
	static final String EMAIL_ADDRESS = "emailAddress";
	static final String EMAIL_PASS = "emailPass";
	static final String GCAL_HASHTAG = "gCalHashTag";
	static final String REFRESH_RATE = "refreshRate";
	// Feature switches
	static final String GCAL_MONITOR = "gcalMonitor";
	static final String REPLY_MONITOR = "replyMonitor";
	
	static final int PROP_LIST_SIZE = 8; // Increment when adding property field.
	static Properties props = new Properties();
	static int latestID = 0;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			File propertiesFile = new File(PROP_FILE_NAME);
			BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	        String str = "";
	        if (propertiesFile.exists()){
				System.out.println("Loading Properties...");
				if (loadProperties(PROP_FILE_NAME)) {
					System.out.println("Properties Loaded.");
				} else {
					System.out.println("\nError loading properties: exiting.");
					System.exit(1);
				}
			} else {
				System.out.println("Properties file not found.");
				System.out.print("Enter path to properties file, or leave blank to create one.\n> ");
		        str = in.readLine();
		        if (str != null) {
		        	if (str.length() > 0) {
		        		if (loadProperties(str)) {
							System.out.println("Properties Loaded.");
						} else {
							System.out.println("\nError loading properties: exiting.");
							System.exit(2);
						}
		        	} else {
		        		System.out.print("Do you want to save the properties you are about to enter? (Y/N) > ");
				        str = in.readLine();
				        setProperties("Y".equalsIgnoreCase(str));
		        	}
				} else {
		        	System.out.println("STD Input was null, exiting.");
		        	System.exit(3);
		        }
			}
			// Now that properties are loaded, we can start the main loop.
	        while (true) {
	        	System.out.println("Starting Loop...");
	        	Twitter twitter = new Twitter(props.getProperty(TWITTER_USER_NAME), 
	    										props.getProperty(TWITTER_PASS));
	    		List<Status> userTimelineStatuses = twitter.getUserTimeline(); // change to since date?
	    		if (props.getProperty(GCAL_MONITOR).equals(ENABLED))
		        	GCalMonitor(userTimelineStatuses);
		        Thread.currentThread().sleep(Integer.parseInt(props.getProperty(REFRESH_RATE))*1000);
	        }
		} catch (Exception e) {
			e.printStackTrace(System.out);
		}
	}
	
	private static boolean loadProperties(String propPath) {
		boolean bool = false;
		try {
			props.load(new FileInputStream(propPath));
			if (props.size() != PROP_LIST_SIZE) {
				System.out.println("File is missing some ("+(PROP_LIST_SIZE-props.size())
									+") properties, you must update.");
				setProperties(true);
			}
			bool = true;
		}
		catch (Exception e) {
			e.printStackTrace(System.out);
		}
		return bool;
	}

	private static void setProperties(boolean save) throws Exception {
		System.out.println("Type values then press ENTER. Setting Name: [Current Value]> ");
		setProperty("Twitter User Name", TWITTER_USER_NAME);
		setProperty("Twitter Password", TWITTER_PASS);
		setProperty("Email Address", EMAIL_ADDRESS);
		setProperty("Email Password", EMAIL_PASS);
		setProperty("Hashtag that indicates a Tweet gets added to GCal (without #)", GCAL_HASHTAG);
		setProperty("Enable Google Calendar Monitor? (Y/N)", GCAL_MONITOR);
		setProperty("Enable @Reply to TXT Monitor? (Y/N)", REPLY_MONITOR);
		setProperty("How long between refreshes (in seconds, 3600 (1h) is suggested)?", REFRESH_RATE);
		if (save)
			props.store(new FileOutputStream(PROP_FILE_NAME), "");
	}
	
	private static void setProperty(String txt, String propID) throws Exception {
		if (props.containsKey(propID)) {
			System.out.println(txt+": ["+props.getProperty(propID)+"]> ");
		} else {
			System.out.println(txt+": > ");
		}
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String str = in.readLine();
        if (str != null) {
        	if (str.length() > 0) {
        		if (txt.contains("(Y/N)")) {
        			if ("Y".equalsIgnoreCase(str))
        				props.setProperty(propID, ENABLED);
        			else
        				props.setProperty(propID, "disabled");
        		} else {
        			props.setProperty(propID, str);
        		}
        	}
		} else {
        	System.out.println("STD Input was null, exiting.");
        	System.exit(4);
        }
	}
	
	private static void GCalMonitor(List<Status> statuses) throws Exception {
		int id;
		String txt = "";
		for (Status status : statuses) {
			id = (int)status.getId();
			txt = status.getText();
			if (id > latestID) {
				if (txt.contains(props.getProperty(GCAL_HASHTAG)))
					addToGCal(txt);
				latestID = id;
				System.out.println("Setting Latest Id: "+id);
			}
		}
	}
	
	private static void addToGCal(String txt) throws Exception {
		String METAFEED_URL_BASE = "http://www.google.com/calendar/feeds/";
		String EVENT_FEED_URL_SUFFIX = "/private/full";
		URL eventFeedUrl;
		try {
			eventFeedUrl = new URL(METAFEED_URL_BASE + props.getProperty(EMAIL_ADDRESS)
					+ EVENT_FEED_URL_SUFFIX);
		} catch (MalformedURLException e) {
			// Bad URL
			System.err.println("Uh oh - you've got an invalid URL.");
			e.printStackTrace();
			return;
		}

		CalendarService service = new CalendarService("TECHNOLOGIC");
		service.setUserCredentials(props.getProperty(EMAIL_ADDRESS), props.getProperty(EMAIL_PASS));
		CalendarEventEntry myEntry = new CalendarEventEntry();
		String eventContent = txt.substring(0, txt.indexOf("#")); 
		boolean isQuickAdd = true;
		myEntry.setContent(new PlainTextConstruct(eventContent));
		myEntry.setQuickAdd(isQuickAdd);
		service.insert(eventFeedUrl, myEntry);
		System.out.println("Added: "+txt);
	}
}
